package com.brutal.minigames.gop;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.RenderedImage;
import java.io.File;
import java.net.URL;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.LinkedList;

import javax.imageio.ImageIO;
import javax.swing.JOptionPane;

import com.brutal.paint.Paint;

import com.rsbuddy.event.listeners.PaintListener;
import com.rsbuddy.script.ActiveScript;
import com.rsbuddy.script.Manifest;
import com.rsbuddy.script.methods.Calculations;
import com.rsbuddy.script.methods.Environment;
import com.rsbuddy.script.methods.Game;
import com.rsbuddy.script.methods.Mouse;
import com.rsbuddy.script.methods.Skills;
import com.rsbuddy.script.methods.Widgets;
import com.rsbuddy.script.util.Random;
import com.rsbuddy.script.util.Timer;
import com.rsbuddy.script.wrappers.Tile;
import com.rsbuddy.script.wrappers.Widget;

import org.rsbuddy.tabs.Inventory;

@Manifest(authors = { "Ramus" }, description = "Plays the Great Orb Project minigame", keywords = {
		"great", "gop", "minigames", "orb", "project", "ramus" }, name = "BrutalGOP", website = "http://scripts.rsbuddy.com/?script=BrutalGOP", version = 1.02)
public class BrutalGOP extends ActiveScript implements MouseListener,
		MouseMotionListener, PaintListener {

	private final LinkedList<Task> tasks = new LinkedList<Task>();
	private int startTokens = -1;
	private long startTime = -1;
	private String status = "Loading...";
	private int startXp = -1;
	private int startLevel = -1;
	private int startRunes = -1;
	private final int tokensId = 13650;
	private final int[] runesId = { 554, 555, 556, 557, 558, 559, 561, 562 };
	private Task currentTask = null;
	private int yellowScore = -1;
	private int greenScore = -1;
	private Team team = null;
	private int won = 0;
	private int lossed = 0;
	private int drawn = 0;
	private Timer uploadStatsTimer = null;
	private int[] uploadedStats = { 0, 0 };
	private String user = null;
	private Paint paint =
			new Paint(
					Skills.RUNECRAFTING,
					getImage(
							"NotesButton.png",
							"http://images1.wikia.nocookie.net/__cb20090912192707/runescape/images/0/0f/Notes_button.png"),
					getImage(
							"RunecraftingIcon.png",
							"http://images1.wikia.nocookie.net/__cb20110305042949/runescape/images/6/64/Runecrafting-icon.png"),
					getImage(
							"Stats.png",
							"http://images2.wikia.nocookie.net/__cb20090708205136/runescape/images/d/d0/Statistics.png"),
					"", "", "");

	@Override
	public boolean onStart() {
		user =
				(String) JOptionPane
						.showInputDialog(
								null,
								"OmniBots Username",
								"If you wish to have/updated a dynamic signature, please type in your OmniBots username. If you do not have an account with OmniBots, please register at http://www.omnibots.comlu.com/",
								JOptionPane.INFORMATION_MESSAGE);
		tasks.add(new Join(Team.RANDOM, false));
		tasks.add(new Play(false));
		startTime = System.currentTimeMillis();
		new Login(isMember()).run();
		return true;
	}

	@Override
	public int loop() {
		if (!Game.isLoggedIn() || !isActive() || isPaused()) {
			return Random.nextInt(300, 500);
		}
		uploadStats(false);
		for (Task task : tasks) {
			if (task.isValid()) {
				currentTask = task;
				currentTask.execute();
			}
		}
		return 0;
	}

	@Override
	public void onFinish() {
		uploadStats(true);
		if (Game.isLoggedIn()) {
			Game.logout(false);
		}
	}

	private void uploadStats(boolean force) {
		int tokensGained =
				(int) ((Inventory.containsOneOf(tokensId) ? Inventory.getCount(
						true, tokensId) : 0) - startTokens);
		int gamesPlayed = (int) (won + drawn + lossed);
		if (!uploadStatsTimer.isRunning() || force) {
			if (uploadedStats[0] < tokensGained
					&& uploadedStats[1] < gamesPlayed || force) {
				try {
					tokensGained = tokensGained - uploadedStats[0];
					gamesPlayed = gamesPlayed - uploadedStats[1];
					final URL url =
							new URL(
									"http://omnibots.comlu.com/brutal/submitgopstats.php?user="
											+ user.toLowerCase() + "tokens="
											+ tokensGained + "games="
											+ gamesPlayed);
					url.openStream();
					uploadedStats[0] += tokensGained;
					uploadedStats[1] += gamesPlayed;
				} catch (Exception e) {
				}
			}
			uploadStatsTimer = new Timer(600000);
		}
	}

	private boolean isMember() {
		return false;
	}

	private int getGreenAltars() {
		final Widget widget = Widgets.get(781);
		int count = 0;
		for (int i = 23; i < 30; i++) {
			if (widget.getComponent(i).getModelId() == 41479) {
				count++;
			}
		}
		return count;
	}

	private int getYellowAltars() {
		final Widget widget = Widgets.get(781);
		int count = 0;
		for (int i = 23; i < 30; i++) {
			if (widget.getComponent(i).getModelId() == 41480) {
				count++;
			}
		}
		return count;
	}

	private void checkScores() {
		if (currentTask instanceof Play) {
			yellowScore = getYellowAltars();
			greenScore = getGreenAltars();
			team = ((Play) currentTask).getTeam();
		} else {
			if (yellowScore > -1 && greenScore > -1) {
				if (yellowScore == greenScore) {
					drawn++;
				} else if (yellowScore > greenScore) {
					won += team == Team.YELLOW ? 1 : 0;
				} else if (yellowScore < greenScore) {
					lossed += team == Team.YELLOW ? 0 : 1;
				}
				yellowScore = -1;
				greenScore = -1;
			}
		}

	}

	private String formatTime(final long millis) {
		final long time = millis / 1000;
		String seconds = Integer.toString((int) (time % 60));
		String minutes = Integer.toString((int) ((time % 3600) / 60));
		String hours = Integer.toString((int) (time / 3600));
		if (hours == "1") {
			hours = hours + " Hour ";
		} else {
			hours = hours + " Hours ";
		}
		if (minutes == "1") {
			minutes = minutes + " Minute ";
		} else {
			minutes = minutes + " Minutes ";
		}
		if (seconds == "1") {
			seconds = seconds + " Second";
		} else {
			seconds = seconds + " Seconds";
		}
		return hours + minutes + seconds;
	}

	private Image getImage(final String fileName, final String imageURL) {
		try {
			File f =
					new File(Environment.getStorageDirectory() + File.separator
							+ fileName);
			if (!f.exists()) {
				Image image = null;
				URL url = new URL(imageURL);
				image = ImageIO.read(url);
				ImageIO.write((RenderedImage) image, "PNG", f);
				return image;
			}
			Image img = ImageIO.read(f);
			return img;
		} catch (Exception e) {
		}
		return null;
	}

	private boolean isPointValid(final Point point) {
		if (point == null || point == new Point(-1, -1)
				|| !Calculations.isPointOnScreen(point)) {
			return false;
		}
		return true;
	}

	private boolean isPointsValid(final Point[] points) {
		for (Point point : points) {
			if (!isPointValid(point)) {
				return false;
			}
		}
		return true;
	}

	private void fillTile(final Graphics2D g, final Tile tile, final Color c) {
		if (tile == null || !Calculations.isTileOnMap(tile)) {
			return;
		}
		final Point bl = Calculations.tileToScreen(tile, 0, 0, 0), br =
				Calculations.tileToScreen(tile, 1, 0, 0), tr =
				Calculations.tileToScreen(tile, 1, 1, 0), tl =
				Calculations.tileToScreen(tile, 0, 1, 0);
		if (!isPointsValid(new Point[] { bl, br, tr, tl })) {
			return;
		}
		final Polygon poly =
				new Polygon(new int[] { bl.x, br.x, tr.x, tl.x }, new int[] {
						bl.y, br.y, tr.y, tl.y }, 4);
		g.setColor(c);
		g.fillPolygon(poly);
		g.setColor(Color.BLACK);
		g.drawPolygon(poly);
	}

	private void drawMouse(final Graphics2D g) {
		final Point cursor = Mouse.getLocation();
		if (!Mouse.isPresent()) {
			return;
		}
		if (System.currentTimeMillis() - Mouse.getPressTime() < 250) {
			g.setColor(Color.RED);
		} else {
			g.setColor(Color.YELLOW);
		}
		g.drawRect(cursor.x - 2, cursor.y - 2, 4, 4);
		g.drawLine(cursor.x - 4, cursor.y, cursor.x - 2, cursor.y);
		g.drawLine(cursor.x + 4, cursor.y, cursor.x + 2, cursor.y);
		g.drawLine(cursor.x, cursor.y - 4, cursor.x, cursor.y - 2);
		g.drawLine(cursor.x, cursor.y + 4, cursor.x, cursor.y + 2);
	}

	@Override
	public void onRepaint(Graphics g1) {
		final Graphics2D g = (Graphics2D) g1;
		g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
				RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		drawMouse(g);
		if (!Game.isLoggedIn() || !isActive() || isPaused()) {
			return;
		}
		if (startXp == -1 && Skills.getCurrentExp(Skills.RUNECRAFTING) > 0) {
			startXp = Skills.getCurrentExp(Skills.RUNECRAFTING);
		}
		if (startLevel == -1 && Skills.getRealLevel(Skills.RUNECRAFTING) > 0
				&& startXp != -1) {
			startLevel = Skills.getRealLevel(Skills.RUNECRAFTING);
		}
		if (startRunes == -1 && startXp != -1) {
			if (!Inventory.containsOneOf(runesId)) {
				startRunes = 0;
			}
			startRunes = Inventory.getCount(true, runesId);
		}
		if (startTokens == -1 && startXp != -1) {
			if (!Inventory.containsOneOf(tokensId)) {
				startTokens = 0;
			} else if (Inventory.containsOneOf(tokensId)) {
				startTokens = Inventory.getCount(true, tokensId);
			}
		}
		status = currentTask.getStatus();
		checkScores();
		if (currentTask instanceof Play) {
			final Play play = (Play) (currentTask);
			if (play.path != null) {
				for (Tile tile : play.path) {
					fillTile(g, tile, Color.BLUE);
				}
			}
			if (play.altarTile != null) {
				fillTile(g, play.altarTile, Color.GREEN);
			}
			if (play.orbTile != null) {
				fillTile(g, play.orbTile, Color.RED);
			}
			if (play.cornerTile != null) {
				fillTile(g, play.cornerTile, Color.GREEN);
			}
			if (play.walkTile != null) {
				fillTile(g, play.walkTile, Color.MAGENTA);
			}
		}
		final long runTime = System.currentTimeMillis() - startTime;
		final int tokensGained =
				(int) ((Inventory.containsOneOf(tokensId) ? Inventory.getCount(
						true, tokensId) : 0) - startTokens);
		final int tokensGainedPerHour =
				(int) ((3600000 / (double) runTime) * tokensGained);
		final int xpGained =
				(int) (Skills.getCurrentExp(Skills.RUNECRAFTING) - startXp);
		final int xpGainedPerHour =
				(int) ((3600000 / (double) runTime) * xpGained);
		final int levelsGained =
				(int) (Skills.getRealLevel(Skills.RUNECRAFTING) - startLevel);
		final int runesCrafted =
				(int) ((Inventory.containsOneOf(runesId) ? Inventory.getCount(
						true, runesId) : 0) - startRunes);
		final int runesCraftedPerHour =
				(int) ((3600000 / (double) runTime) * runesCrafted);
		final long timeToLevel =
				xpGainedPerHour > 0 ? (int) ((Skills
						.getExpToNextLevel(Skills.RUNECRAFTING) * 3600 / xpGainedPerHour) * 1000)
						: 0;
		final int gamesPlayed = (int) (won + drawn + lossed);
		final int gamesPlayedPerHour =
				(int) ((3600000 / (double) runTime) * gamesPlayed);
		final int gamesWon = (int) (won);
		final int gamesWonPerHour =
				(int) ((3600000 / (double) runTime) * gamesWon);
		final int gamesDrawn = (int) (drawn);
		final int gamesDrawnPerHour =
				(int) ((3600000 / (double) runTime) * gamesDrawn);
		final int gamesLossed = (int) (lossed);
		final int gamesLossedPerHour =
				(int) ((3600000 / (double) runTime) * gamesLossed);
		final NumberFormat numberFormat = new DecimalFormat("#,###,###");
		if (paint != null) {
			paint.updateTabText(paint.getTab(1), "BrutalGOP "
					+ getClass().getAnnotation(Manifest.class).version()
					+ " By Ramus\nStatus: " + status + "\nTime Running: "
					+ formatTime(runTime));
			paint.updateTabText(
					paint.getTab(2),
					"Tokens gained: " + numberFormat.format(tokensGained)
							+ " (" + numberFormat.format(tokensGainedPerHour)
							+ "/H)\nRunes Crafted: "
							+ numberFormat.format(runesCrafted) + " ("
							+ numberFormat.format(runesCraftedPerHour)
							+ "/H)\nGames Played: " + gamesPlayed + " ("
							+ gamesPlayedPerHour + "/H)\nGames Won: "
							+ gamesWon + " (" + gamesWonPerHour
							+ "/H)\nGames Drawn: " + gamesDrawn + " ("
							+ gamesDrawnPerHour + "/H)\nGames Lossed: "
							+ gamesLossed + " (" + gamesLossedPerHour + "/H)");
			paint.updateTabText(
					paint.getTab(3),
					"Levels Gained: "
							+ levelsGained
							+ "\nXP Gained: "
							+ numberFormat.format(xpGained)
							+ " ("
							+ numberFormat.format(xpGainedPerHour)
							+ "/H)\nXP To Level: "
							+ (Skills.getRealLevel(Skills.RUNECRAFTING) + 1)
							+ ": "
							+ numberFormat.format(Skills
									.getExpToNextLevel(Skills.RUNECRAFTING))
							+ "\nTime To Level: "
							+ (Skills.getRealLevel(Skills.RUNECRAFTING) + 1)
							+ ": " + formatTime(timeToLevel));
			paint.onRepaint(g);
		}
	}

	@Override
	public void mouseDragged(MouseEvent e) {
	}

	@Override
	public void mouseMoved(MouseEvent e) {
		if (paint != null) {
			paint.mouseMoved(e);
		}
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		if (paint != null) {
			paint.mouseClicked(e);
		}
	}

	@Override
	public void mouseEntered(MouseEvent e) {
	}

	@Override
	public void mouseExited(MouseEvent e) {
	}

	@Override
	public void mousePressed(MouseEvent e) {
	}

	@Override
	public void mouseReleased(MouseEvent e) {
	}
}